import { Request } from '@/uni_modules/endless-ui/utils';
import { toastApp } from '@/common/utils/toast';
import { AppCookie } from '@/common/utils';
import { useUser } from '@/common/stores';
import { LOCALE, REQUEST_SUCCESS_CODE, TOKEN_NAME } from '@/env';
import { empty, isObj, isArray, isBoolean } from '@/common/utils';
import type { ResponseData, PagingData, pageParam, RequestFromType, IMResponseData, RequestOptionCustom } from './type';

let user: ReturnType<typeof useUser>;
const setStores = () => {
	if (!user) {
		user = useUser();
	}
};

const request = new Request<ResponseData, RequestOptionCustom>({
	baseURL: import.meta.env.VITE_API_URL,
	modifyData: (_request: Promise<any>) =>
		new Promise((resolve, reject) => {
			_request
				.then((res) => {
					if (res?.statusCode === 200) {
						resolve(res.data);
					} else {
						reject(res);
					}
				})
				.catch((res) => {
					if (res?.statusCode === 200) {
						reject(res.data);
					} else {
						reject(res);
					}
				})
				.finally(() => {
					uni.hideLoading();
				});
		})
});

const setRequestBaseURL = (url: string) => {
	request.setConfig((config) => {
		config.baseURL = url;
		return config;
	});
};
let IMBaseUrl = import.meta.env.VITE_IM_HTTP_API_URL;
const setIMRequestBaseURL = (url: string) => {
	IMBaseUrl = url;
};
const getIMBaseUrl = () => IMBaseUrl;

const getRequestConfigHeader = () => {
	const Authorization = uni.getStorageSync('token');
	const tenant = uni.getStorageSync('tenant');
	let header: Record<string, string> = {
		lang: uni.getStorageSync('locale') || LOCALE
	};
	if (Authorization) {
		header[TOKEN_NAME] = Authorization;
	}
	if (tenant) {
		header['tenant'] = tenant;
	}
	// #ifdef PRIVATE
	const storeId = uni.getStorageSync('storeId');
	if (tenant) {
		header['StorePrivateSphereId'] = storeId;
	}
	// #endif

	return header;
};
// 设置请求头的token等字段，只需在初始化或有改动时设置即可，无需在拦截器中每次都去判断，设置请求头，减少不需要的操作
const setRequestHeader = () => {
	request.setConfig((config) => {
		let header: Record<string, string> = getRequestConfigHeader();

		header['Content-Type'] = 'application/x-www-form-urlencoded';

		config.header = header;
		return config;
	});
};

const deleteNullValue = (data?: Record<string, any> | string) => {
// #ifdef H5
	if (!isObj(data) && !(data instanceof FormData)) return {};
	// #endif
	// #ifndef H5
	if (!isObj(data)) return {};
	// #endif
	Object.keys(data).forEach((key) => {
		const val = data[key];
		if (!isBoolean(val)&&!val && val !== 0) {
			delete data[key];
		}
	});
	return data;
};

request.interceptors.request.use((config) => {
	// #ifdef APP-NVUE
	// NVUE下request的全局变量是无法共享的，会导致config的header为空，需重新设置
	config.header = config.header ? { ...config.header, ...getRequestConfigHeader() } : getRequestConfigHeader();
	// #endif
	// #ifndef H5
	config.header.Cookie = AppCookie.getAll(); // 将每次的请求头中加入Cookies
	// #endif
	/* 请求之前拦截器 */
	// 不传auth或auth不为false，则该请求视为需要登录后请求
	
	if (config.custom?.auth !== false) {
		let token = uni.getStorageSync('token');
		// 所有需要登录的请求都不能在app初始化前调用，否则会因为pinia没有初始化而报错
		setStores();
		if (!token) {
			user.isLogin = false;

			if (config.custom?.goLogin) {
				let pages = getCurrentPages()[0];
				if (pages && pages.route !== 'pages/splash') {
					uni.$_goLogin();
				}
			}
			console.error('暂未登录,已阻止此次API请求~' + '接口：' + config.url);

			return Promise.reject(config);
		}
	}

	if (config.custom?.isLoading) {
		uni.showLoading({
			title: 'loading...',
			mask: true
		});
	}
	if (import.meta.env.DEV) {
		if (RegExp(/mock/).test(config.url || '')) {
			let reg = new RegExp('mock', 'g');
			config.url = config?.url?.replace(reg, '') || '';
			config.baseURL = 'http://192.168.1.117/mock/mock/ishop';
		}
	}
	let location = uni.getStorageSync('userGeolocation');
	if (!empty(config.data)) {
		if (isArray(config.data)) {
			config.data = JSON.stringify(config.data);
		} else {
			if (isObj(config.data) && config.data?.location) {
				// 如果接口参数内有经纬度，则使用参数的经纬度作为当前的经纬度
				location = { ...config.data.location };
				delete config.data.location;
			}
			if (config.custom?.filter !== false) {
				config.data = deleteNullValue(config.data);
			}
			if (isObj(config.data)&&config.custom?.isLocation) {
				config.data.latitude = location.latitude;
				config.data.longitude = location.longitude;
			}
		}
	}

	if (location?.latitude) {
		if (config.custom?.isLocation) {
			const locationHeader = {
				'X-LOCATION-LONGITUDE': location.longitude,
				'X-LOCATION-LATITUDE': location.latitude
			};
			config.header = config.header ? { ...config.header, ...locationHeader } : locationHeader;
		}
		config.header.latitude = location.latitude;
		config.header.longitude = location.longitude;
	}
	return config;
});
request.interceptors.response.use((response) => {
	if (response.config.custom?.isLoading) {
		uni.hideLoading();
	}
	if (response.config.custom?.showMsg) {
		toastApp(response.data.msg);
	}
	// #ifndef H5
	response.cookies?.forEach?.((item) => {
		const arr = item.split(';')[0].split('=');
		AppCookie.set(arr[0], arr[1]);
	});
	// #endif

	/* 请求之后拦截器 */
	// code非为成功状态，且不是IM的接口类型，一律抛错
	if (REQUEST_SUCCESS_CODE.includes(response.data.code) || response.data.ok) {
		return response;
	}
	if (response.data.code === 401 || response.data.code === 403 || (isBoolean(response.data.ok) && response.data.code === 1001)) {
		// 普通接口请求登录状态过期或IM接口请求登录状态过期，则清除登录信息并跳转登录页
		user?.outLogin?.();
		setRequestHeader();
		AppCookie.removeAll();
		let pages = getCurrentPages()[0];
		if (pages && pages.route !== 'pages/splash') {
			uni.$_goLogin();
		}
	} else if (response.data.code === 503) {
		// 平台已过期，代表租户key错误或无效
		uni.reLaunch({
			url: '/pages/404?type=2'
		});
	} else {
		// 其它状态一律视为错误状态，显示接口msg字段
		!isBoolean(response.config.custom?.showMsg) && toastApp(response.data.msg);
		if (response.config.custom?.getError) {
			return response;
		}
	}

	return Promise.reject(response);
});

export { ResponseData, IMResponseData, pageParam, PagingData, RequestFromType, setRequestHeader, setRequestBaseURL, setIMRequestBaseURL, getIMBaseUrl };
export default request;
